home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_0_m.arj / DST100.ASM < prev    next >
Assembly Source File  |  1988-11-09  |  38KB  |  944 lines

  1. page 88,132
  2. title DST.COM - DriveST.ASM
  3. ;-----------------------------------------------------------------------|
  4. ;                PUBLIC DOMAIN MATERIAL by ScanSoft(tm)                 |
  5. ;             6402 Ingram Rd., San Antonio, TX  78238                   |
  6. ;-----------------------------------------------------------------------|
  7. ;  program:      DriveST.ASM (DST.COM)                                  |
  8. ;                                                                       |
  9. ;  version:      1                                                      |
  10. ;                                                                       |
  11. ;       by:      Cornel Huth                                            |
  12. ;                                                                       |
  13. ;     date:      Nov 05 88                                              |
  14. ;                                                                       |
  15. ; function:      display drive status on                                |
  16. ;                  line 26 of CGA, EGA/VGA and line 1 of MDA            |
  17. ;                                                                       |
  18. ;   caller:      user timer interrupt 1Ch (18.2 times/sec)              |
  19. ;                                                                       |
  20. ;      use:    C>DST    * install TSR                                   |
  21. ;                DST /- * remove from memory (if possible)              |
  22. ;                DST /d * make dormant (norm screen, unchain if poss)   |
  23. ;                DST /r * restore status line; awaken if dormant        |
  24. ;                DST /a * autopark HD C:(after 30 seconds of inactivity)|
  25. ;                                                                       |
  26. ;                                                                       |
  27. ;    notes:      CPU overhead: 4.77 MHz 8088  3.2                       |
  28. ;                              8.00 MHz 8088  1.8                       |
  29. ;                              6.00 MHz 80286 0.5                       |
  30. ;                              when DORMANT   none                      |
  31. ;                                                                       |
  32. ;                if using MDA, press <Alt> to deactivate status printing|
  33. ;                   on line 1 or use Scroll Lock (on) for continuous    |
  34. ;                   non-display (allows viewing of line 1)              |
  35. ;                                                                       |
  36. ;------------------------------------------------------------------------
  37.  
  38. subttl BIOS segment description
  39.  
  40. ;DEBUGCGA        equ 1
  41.  
  42. BIOS_SEG        SEGMENT AT 0040h
  43.                 ORG 17h
  44. KBDflags1       db ?            ;keyboard toggle flags
  45.                 ORG 41h
  46. status          db ?            ;controller status (not all BIOS's update here)
  47. drive           db ?            ;low nybble = 0 then A:
  48.                                 ;low nybble = 1 then B:
  49.                                 ;low nybble >=8 then HD
  50. headHD          db ?            ;current HD head  (0 to heads on device - 1)
  51. cylHI           label byte      ;bits 6 & 7 represent HI cylinder * 256
  52. secHD           label byte      ;bits 0 - 5 represent sector of HD only
  53.                 db ?
  54. cylLO           db ?            ;LO cylinder (0 - 255 + (cylHI * 256)if HD)
  55. headFD          db ?            ;current floppy head (0 or 1)
  56. secFD           db ?            ;sector of floppy only
  57.                 ORG 49h
  58. modeCRT         db ?            ;current mode of video system
  59.                 ORG 62h
  60. pageCRT         db ?            ;active page of display
  61.                 ORG 63h
  62. addrCRTC        dw ?            ;CRTC address register I/O port
  63.                 ORG 87h
  64. EGAinfo         db ?            ;EGA info byte (0 only if 64K EGA or no EGA)
  65. EGAinfo2        db ?            ;checked if EGAinfo = 0 (this is 0 if no EGA)
  66.  
  67. BIOS_SEG        ENDS
  68.  
  69. subttl Resident code and data
  70.  
  71. DriveST_SEG     SEGMENT BYTE PUBLIC 'CODE'
  72.                 ASSUME cs:DriveST_SEG,ds:DriveST_SEG,es:NOTHING
  73.  
  74.                 org 100h
  75.                 ;need 16 bytes of constant data after go: for DUP install check
  76.  
  77. go:             jmp start
  78.  
  79. checkdata       db 'DST v1.0 (PD)'
  80.  
  81. ERRORMSG        db 'ERROR '
  82. OKMSG           db 'OK    '
  83. PARKMSG         db 'PARKED'
  84.  
  85. EGA_data        dw 5    ;registers to change for EGA/VGA (reg, data)
  86. EGA_26_data     db 06h,07Ah,12h,06Bh,15h,06Ch,10h,06Ch,16h,000h
  87. EGA_25_data     db 06h,06Ch,12h,05Dh,15h,05Eh,10h,05eh,16h,00Ah
  88. EGA_VGA         db 0
  89.  
  90. M6845_data      dw 1    ;registers to change
  91. M6845_26_data   db 06h,26
  92. M6845_25_data   db 06h,25
  93. CGA             db 0    ;CGA uses the M6845 CRTC (MCGA should be compatible)
  94.  
  95. M6845_data7     dw 0    ;registers to change
  96. M6845_26_data7  db 0,0
  97. M6845_25_data7  db 0,0
  98. MDA             db 1    ;MDA is 'worst' case
  99.  
  100. VALIDMODE       db 0    ;= 1 if operating in a compatible video mode
  101.  
  102. WasError        db 0    ;= 32 if drive error (bg from blk on grn to blk on red)
  103.  
  104. Busy1C          dw 0    ;= 1 if already in our New_1C routine
  105. OLD_1C          dd ?    ;interrupt vector for old user timer interrupt
  106.  
  107. CRTCaddr        dw 03D4h  ;CRTC reg addr
  108. Video_Seg       dw 0B800h ;segment of video diplay
  109. Video_Page      db 0      ;active video page
  110. Video_PageOff   dw 0      ;offset into video segment of page
  111.  
  112. CmdLineParm     db 0    ;command line parameter  (preceded by a /)
  113.  
  114. StatLnOff       dw 0    ;offset into video buffer of Status line (4000/26,0/1)
  115. StatLnCol       dw 0    ;column of first characater of StatLn
  116. StatLnAttr      db 0    ;character attribute of StatLn
  117. StatLn          db 'drv:   cyl:      sec:    head:   stat:                                          '
  118. StatLnend       label word
  119.  
  120. TickTrip        equ 546         ;ticks approx = 30 seconds (546/18.2=30)
  121.  
  122. ticks           dw 0    ;tick cnt since HD active (if DoAuto and not parked)
  123. DoAuto          db 0    ;= 1 then park if ticks > TickTrip
  124. Parked          db 0    ;= 1 then HD is already parked
  125. JustPark        db 0    ;= 1 if we just parked, = 0 if not
  126. LastCylSec      db 0    ;last cylinder/sector in BIOS form
  127. LastCyl         db 0    ;last cylinder (low)
  128. LastSec         db 0    ;last sector
  129. LastHead        db 0    ;last head
  130.       
  131. New_1C          PROC FAR
  132.                 ASSUME  ds:NOTHING, es:NOTHING
  133.                 sti
  134.                 push    ax
  135.                 push    bx
  136.                 push    cx
  137.                 push    dx
  138.                 push    bp
  139.                 push    di
  140.                 push    si
  141.                 push    es
  142.                 push    ds
  143.                 pushf                   ;preserve callings flags in case needed
  144.                 cld                     ;a must
  145.                 mov     ax,cs
  146.                 mov     ds,ax           ;point ds to data
  147.                 ASSUME  ds:DriveST_SEG
  148.                 inc     ticks           ;let's time the need for a park
  149.                 cmp     Busy1C,0        ;are we BUSY?
  150.                 jne     New_1Cxit
  151.                 mov     Busy1C,1        ;no, make us BUSY
  152.  
  153.                 mov     ax,0040h
  154.                 mov     es,ax
  155.                 ASSUME  es:NOTHING
  156.  
  157.                 cmp     DoAuto,1        ;autopark on?
  158.                 je      New_1C1         ;yes
  159.                 mov     ticks,0         ;no, zero ticks for a fresh start on /a
  160.  
  161. New_1C1:        call    Xlate_BIOS      ;es->BIOS
  162.                 cmp     ticks,TickTrip  ;need to park?
  163.                 jb      New_1C2         ;no
  164.                 cmp     Parked,1        ;already parked?
  165.                 je      New_1C2         ;yes
  166.                 call    ParkC
  167.  
  168. New_1C2:        call    Get_Video_Info  ;es->BIOS (after)
  169.                 cmp     VALIDMODE,1     ;are we valid?
  170.                 jne     New_1Cxit       ;no
  171.                 lea     dx,StatLn
  172.                 mov     cx,offset StatLnend - offset StatLn
  173.                 mov     ah,StatLnAttr
  174.  
  175.                 cmp     MDA,1
  176.                 jne     New_1C3
  177.                 test    es:KBDflags1,18h;is <Alt> down or <Scroll Lock> on?
  178.                 jnz     New_1Cxit       ;yes, no display of MDA status
  179.  
  180.                 cmp     WasError,0
  181.                 je      New_1C4
  182.  
  183.                 mov     ah,07           ;normal video on error for MDA
  184.                 jne     New_1C4
  185.  
  186. New_1C3:        add     ah,WasError     ;WasError = (2*16) if disk error
  187.  
  188. New_1C4:        mov     bx,StatLnCol    ;start column of StatLn
  189.                 call    Write_StatLn
  190.  
  191. New_1Cxit:      popf
  192.                 pop     ds
  193.                 pop     es
  194.                 ASSUME  ds:NOTHING, es:NOTHING
  195.                 pop     si
  196.                 pop     di
  197.                 pop     bp
  198.                 pop     dx
  199.                 pop     cx
  200.                 pop     bx
  201.                 pop     ax
  202.                 cli                     ;turn off (OLD_1C or IRET turns it on)
  203.                 mov     cs:Busy1C,0     ;make us READY
  204.                 jmp     cs:OLD_1C
  205. New_1C          ENDP
  206.  
  207. ;
  208. ; get video system information
  209. ;
  210.  
  211. Get_Video_Info  PROC NEAR
  212.                 ASSUME  ds:DriveST_SEG, ds:NOTHING       
  213.                 mov     ax,0040h
  214.                 mov     es,ax
  215.                 ASSUME  es:NOTHING
  216.                 mov     MDA,1           ;assume 'worst case'
  217.                 mov     VALIDMODE,0     ;ditto
  218.                 mov     CGA,0           ;these may change from zero
  219.                 mov     EGA_VGA,0       ;so zero then here
  220.                 cmp     es:modeCRT,2    ;valid modes are 2, 3, 7
  221.                 jb      GVIjmp          ;below 2 invalid
  222.                 cmp     es:modeCRT,7    ;7 ok
  223.                 je      GVI0
  224.                 cmp     es:modeCRT,4
  225.                 jb      GVI0            ;2 or 3 ok
  226.  
  227. GVIjmp:         jmp     GVIxit
  228.  
  229.                 ; get the CRTC port address
  230.  
  231. GVI0:           cmp     es:addrCRTC,03D4h       ;color?
  232.                 jne     GVI1
  233.                 mov     MDA,0                   ;yes, we know it's not mono
  234.                 mov     Video_Seg,0B800h        ;video base segment of color
  235.                 mov     CRTCaddr,03D4h          ;its controller
  236.                 mov     StatLnOff,4000          ;StatLn offset (line 26)
  237.                 mov     StatLnCol,0             ;StatLn column (col 1)
  238.                 mov     StatLnAttr,0+(2*16)     ;black on green
  239.                 je      GVI2
  240.  
  241. GVI1:           mov     Video_Seg,0B000h        ;mono's video base segment
  242.                 mov     CRTCaddr,03B4h          ;its controller
  243.                 mov     StatLnOff,0             ;StatLn offset (line 1)
  244.                 mov     StatLnCol,0             ;StatLn column (col 1)
  245.                 mov     StatLnAttr,70h          ;reverse video
  246.                 jmp     short GVI4
  247.  
  248. GVI2:           cmp     es:EGAinfo,0            ;64K EGA or no EGA?
  249.                 jne     GVI2a                   ;no, an EGA with >64K
  250.                 cmp     es:EGAinfo2,0           ;no EGA at all?
  251.                 je      GVI3                    ;should be a CGA
  252. GVI2a:          mov     EGA_VGA,1
  253.                 jne     GVI4
  254.  
  255. GVI3:           mov     CGA,1           ;it's CGA (MCGA may work, not tested)
  256. GVI4:           mov     VALIDMODE,1
  257.  
  258.                 ;calculate offset into video buffer of the current page
  259.  
  260.                 mov     al,es:pageCRT
  261.                 cmp     al,Video_Page   ;still using same page?
  262.                 je      GVIxit
  263.                 mov     Video_Page,al   ;no, inform DST of new page
  264.                 xor     bh,bh
  265.                 mov     bl,Video_Page
  266.                 mov     ax,1000h        ;video page size (based on 80 X 25)
  267.                 mul     bx              ;times page (0-7)
  268.                 mov     Video_PageOff,ax
  269. GVIxit:         ret
  270. Get_Video_Info  ENDP
  271.  
  272. ;
  273. ; program CRTC to display 26 lines
  274. ;
  275.  
  276. Set_Line26      PROC NEAR
  277.                 ASSUME  ds:DriveST_SEG
  278.  
  279.                 cmp     MDA,1                   ;skip if MDA
  280.                 jne     SL261
  281.                 ret
  282.  
  283. SL261:          mov     dx,CRTCaddr             ;CRTC port address
  284.                 cmp     EGA_VGA,1
  285.                 jne     SL26_M6845
  286.                 mov     cx,EGA_data             ;set up EGA (byte 1 = # data)
  287.                 mov     si,offset EGA_26_data
  288.                 je      SL26_LR
  289. SL26_M6845:     mov     cx,M6845_data           ;set up M6845 (CGA/MCGA)
  290.                 mov     si,offset M6845_26_data
  291. SL26_LR:        cli                             ;interrupts off
  292. SL26_LR1:       lodsb
  293.                 out     dx,al                   ;CRTC register
  294.                 lodsb
  295.                 inc     dx
  296.                 out     dx,al                   ;data
  297.                 dec     dx
  298.                 loop    SL26_LR1
  299.                 sti                             ;interrupts on
  300.                 ret
  301. Set_Line26      ENDP
  302.  
  303. ;
  304. ; program CRTC to display 25 lines
  305. ;
  306.  
  307. Set_Line25      PROC NEAR
  308.                 ASSUME  ds:DriveST_SEG
  309.  
  310.                 cmp     MDA,1                   ;skip if MDA
  311.                 jne     SL251
  312.                 ret
  313.  
  314. SL251:          mov     dx,CRTCaddr             ;as Set_Line26
  315.                 cmp     EGA_VGA,1
  316.                 jne     SL25_M6845
  317.                 mov     cx,EGA_data
  318.                 mov     si,offset EGA_25_data
  319.                 jmp     short SL25_LR
  320. SL25_M6845:     mov     cx,M6845_data
  321.                 mov     si,offset M6845_25_data
  322. SL25_LR:        cli
  323. SL25_LR1:       lodsb
  324.                 out     dx,al
  325.                 lodsb
  326.                 inc     dx
  327.                 out     dx,al
  328.                 dec     dx
  329.                 loop    SL25_LR1
  330.                 sti
  331.                 ret
  332. Set_Line25      ENDP
  333.  
  334. ;
  335. ; write the status
  336. ;
  337.  
  338. Write_StatLn    PROC NEAR
  339.                 ASSUME  ds:DriveST_SEG
  340.  
  341.                 ;ENTER with...
  342.                 ;ds:dx -> DST write buffer
  343.                 ;cx: length of write buffer
  344.                 ;bx: start in this column of line
  345.                 ;ah: attribute of characters in line
  346.  
  347.                 mov     bp,Video_Seg
  348.                 mov     es,bp
  349.                 ASSUME  es:NOTHING
  350.                 shl     bx,1             ;multiply column by 2 (2 bytes/column)
  351.                 add     bx,Video_PageOff ;add adjustment for video page
  352.                 add     bx,StatLnOff     ;add offset into video buff of StatLn
  353.                 mov     di,bx            ;es:di -> destination
  354.                 mov     si,dx            ;ds:si -> source
  355. WR26:           lodsb                    ;get a character from the write buffer
  356.                 stosw                    ;store it and the attribute
  357.                 loop    WR26             ;print cx char/attr pairs
  358.                 ret
  359. Write_StatLn    ENDP
  360.  
  361. Xlate_BIOS      PROC NEAR
  362.                 ASSUME  ds:DriveST_SEG, es:NOTHING
  363.                 ;es->BIOS SEG
  364.                 mov     al,es:drive     ;controller status/drive
  365.  
  366.                 mov     di,offset StatLn+38
  367.                 mov     cx,6            ;length of messages
  368.  
  369.                 test    al,11000000b    ;test for normal termination
  370.                 jz      XLB1
  371.                 lea     dx,ERRORMSG     ;error of some sort
  372.                 mov     si,dx
  373.                 mov     WasError,(2*16) ;attr=red bg on error (attr+WasError)
  374.                 jmp     short XLB2
  375.  
  376. XLB1:           lea     dx,OKMSG        ;normal termination
  377.                 and     al,0Fh          ;isolate low nybble
  378.                 cmp     al,8
  379.                 jb      XLB1a           ;a floppy
  380.                 cmp     Parked,1        ;are we parked?
  381.                 jne     XLB1a
  382.                 lea     dx,PARKMSG      ;yes
  383. XLB1a:          mov     si,dx
  384.                 mov     WasError,0      ;normal attr
  385.  
  386. XLB2:           push    es
  387.                 push    cs
  388.                 pop     es              ;es:di -> write buffer
  389.                 ASSUME  es:NOTHING
  390.  
  391.                 rep     movsb           ;write the message to the write buffer
  392.                 pop     es              ;get back es->BIOS
  393.                 ASSUME  es:NOTHING
  394.  
  395.                 cmp     al,8            ;again, <8 = floppy
  396.                 jnb     XL_HD
  397.                 jmp     XL_floppy
  398.  
  399. XL_HD:          mov     al,"C"          ;I am assuming one HD and that it is C:
  400.                 mov     [StatLn+4],al
  401.  
  402.                 mov     al,es:headHD    ;head
  403.  
  404.                 cmp     LastHead,al     ;* check last head
  405.                 je      XLB3
  406.                 mov     ticks,0         ;different so zero ticks (safe)
  407.                 mov     LastHead,al     ;update new last head
  408.                 cmp     JustPark,1      ;just did a park?
  409.                 je      XLB3            ;yes
  410.                 mov     Parked,0        ;no, then we cannot be parked
  411.  
  412. XLB3:           add     al,'0'
  413.                 mov     [StatLn+30],al
  414.  
  415.                 mov     ah,es:cylHI     ;let's get the cyl hi
  416.                 mov     LastCylSec,ah   ;used by ParkErrorError only
  417.                 rol     ah,1            ;move cyl hi bits @ 6&7 to bits 0&1
  418.                 rol     ah,1
  419.                 and     ah,00000011b    ;isolate cyl hi
  420.                 mov     al,es:cylLO     ;cylinder low (ax = 10 bit cylinder)
  421.  
  422.                 cmp     LastCyl,al      ;* check last cylinder low (safe enough)
  423.                 je      XLB4            ;* note we're not checking cyl hi
  424.                 mov     ticks,0         ;different so zero ticks
  425.                 mov     LastCyl,al      ;update new last cylinder
  426.                 cmp     JustPark,1      ;just did a park?
  427.                 je      XLB4            ;yes
  428.                 mov     Parked,0        ;no, then we cannot be parked
  429.  
  430. XLB4:           mov     di,offset StatLn+11
  431.                 mov     cx,4            ;number of digits
  432.                 call    AX2DEC
  433.  
  434.                 mov     al,es:cylHI     ;isolate sector
  435.                 and     al,00111111b    ;bits 0 - 5
  436.  
  437.                 cmp     LastSec,al      ;* check last sector
  438.                 je      XLB5
  439.                 mov     ticks,0         ;different so zero ticks
  440.                 mov     LastSec,al      ;update new last sector
  441.                 cmp     JustPark,1      ;just did a park?
  442.                 je      XLB5            ;yes
  443.                 mov     Parked,0        ;no, then we cannot be  parked
  444.  
  445. XLB5:           xor     ah,ah
  446.                 mov     di,offset StatLn+21-2   ;-2 since cx = 4-2
  447.                 mov     cx,2
  448.                 call    AX2DEC
  449.                 mov     JustPark,0      ;no longer just did a park now
  450.                 ret
  451.  
  452. XL_floppy:      and     al,00000011b    ;drive 0-3
  453.                 add     al,'A'
  454.                 mov     [StatLn+4],al
  455.  
  456.                 mov     al,es:headFD
  457.                 and     al,00000001     ;head 0-1
  458.                 add     al,'0'
  459.                 mov     [StatLn+30],al
  460.  
  461.                 xor     ah,ah
  462.                 mov     al,es:cylLO     ;track
  463.                 mov     di,offset StatLn+11
  464.                 mov     cx,4            ;number of digits (HD cover up)
  465.                 call    AX2DEC
  466.  
  467.                 xor     ah,ah
  468.                 mov     al,es:secFD
  469.                 mov     di,offset StatLn+21-2   ;-2 since cx = 4-2
  470.                 mov     cx,2
  471.                 call    AX2DEC
  472.                 ret
  473. Xlate_BIOS      ENDP
  474.                     
  475.                     
  476. ;  ENTER with:
  477. ;       ax = int value 0-9999
  478. ;       cx = number of digits to interpret
  479. ;       di -> buffer
  480. ;  EXIT with:
  481. ;       ASCII value of ax in di->buffer
  482.  
  483. AX2DEC          PROC NEAR
  484.                 ASSUME  ds:DriveST_SEG
  485.  
  486.                 ;divide by 10 - get remainder
  487.                 mov     bx,10                   ; divisor
  488.                 xor     dx,dx                   ; using AX as dividend
  489.                 div     bx                      ; remainder in dx
  490.                 add     dl,"0"                  ; to ASCII
  491.                 mov     byte ptr [di+3],dl      ; store it
  492.                 cmp     cx,1
  493.                 je      AX2DECxit
  494.                 ;tens
  495.                 xor     dx,dx
  496.                 div     bx
  497.                 add     dl,"0"
  498.                 mov     byte ptr [di+2],dl
  499.                 cmp     cx,2
  500.                 je      AX2DECxit
  501.                 ;hundreds
  502.                 xor     dx,dx
  503.                 div     bx
  504.                 add     dl,"0"
  505.                 mov     byte ptr [di+1],dl
  506.                 cmp     cx,3
  507.                 je      AX2DECxit
  508.                 ;thousands
  509.                 xor     dx,dx
  510.                 div     bx
  511.                 add     dl,"0"
  512.                 mov     byte ptr [di],dl
  513. AX2DECxit:      ret
  514. AX2DEC          ENDP
  515.  
  516.  
  517. ParkC           PROC NEAR
  518.                 ASSUME  ds:DriveST_SEG
  519.  
  520.                 mov     dl,80h
  521.                 mov     ah,08h
  522.                 int 13h                 ;get HD info (when dl >= 80h)
  523.                                         ;ch = last cyl(lo) position
  524.                                         ;cl = cyl(hi)(bits 6-7) & sec/cyl (0-5)
  525.                                         ;dh = sides (0 based)
  526.                                         ;dl = number of HD's
  527.                 cmp     dl,0            ;any HD's?
  528.                 je      ParkCxit
  529.                 cmp     dl,80h          ;HD BIOS not there?
  530.                 je      ParkCxit
  531.  
  532.                 mov     dl,80h          ;select first HD
  533.                 push    cx              ;save cyl/sec info
  534.                 rol     cl,1            ;move bits 6 & 7 to bit positions 0 & 1
  535.                 rol     cl,1            ; moving sec/cyl to bits 2-7
  536.                 xchg    cl,ch           ;put hi cyl&sec in ch and lo cyl in cl
  537.                 and     cx,03FFh        ;make 10-bit last cyl & zero sector
  538.                 inc     cx              ;let's make it last cyl+1
  539.                 xchg    cl,ch           ;put hi cyl in cl and lo cyl in ch
  540.                 ror     cl,1            ;move bits 0 & 1 back to bit pos 6 & 7
  541.                 ror     cl,1            ; moving sec/cyl back to bits 0 - 5
  542.                 or      cl,01h          ;sector to 1 (physical HD sector 0)
  543.                 mov     dh,0            ;head to 0
  544.                 mov     ah,0Ch          ;seek to cylinder (AT BIOS documented)
  545.                 int 13h                 ; should work for >10MEG HD controller
  546.                 jc      ParkError       ;an error
  547.                 mov     Parked,1        ;we're parked
  548.                 mov     JustPark,1      ;just now did it
  549.                 mov     ticks,0         ;zero (for completeness)
  550.                 clc
  551.                 pop     cx              ;remove saved cyl/sec info
  552. ParkCxit:       ret
  553.  
  554. ParkError:      mov     dl,80h          ;select first HD
  555.                 pop     cx              ;get saved cyl/sec info
  556.                 rol     cl,1
  557.                 rol     cl,1
  558.                 xchg    cl,ch
  559.                 and     cx,03FFh        ;no inc this time
  560.                 xchg    cl,ch
  561.                 ror     cl,1
  562.                 ror     cl,1
  563.                 or      cl,01h
  564.                 mov     dh,0
  565.                 mov     ah,0Ch          ;seek to last cyl (not last cyl+1)
  566.                 int 13h
  567.                 jc      ParkErrorError  ;another error
  568.                 mov     Parked,1
  569.                 mov     JustPark,1
  570.                 mov     ticks,0
  571.                 clc
  572. ParkErrorxit:   ret
  573.  
  574. ParkErrorError: mov     dl,80h
  575.                 mov     ch,LastCyl      ;get last cylinder low
  576.                 mov     cl,LastCylSec   ;and last cylinder hi and sector
  577.                 mov     dh,0
  578.                 mov     ah,0Ch          ;seek to previous cylinder
  579.                 int 13h
  580.                 mov     Parked,0
  581.                 mov     JustPark,0
  582.                 mov     ticks,0
  583.                 stc
  584.                 ret
  585. ParkC           ENDP
  586.  
  587. subttl Installation code
  588.  
  589.                 ;===============================================
  590.                 ;let's install it - code after start is not kept
  591.                 ;===============================================
  592.  
  593.                 ASSUME  cs:DriveST_SEG,ds:DriveST_SEG
  594.  
  595. start:          cld
  596.                 lea     dx, Copyright   ;it is PD material
  597.                 mov     ah,9
  598.                 int     21h             ;DOS print string
  599.  
  600.                 call    GetParm
  601.  
  602.                 ;---------------------
  603.                 not     byte ptr go     ;modify to avoid self-match
  604.                 xor     bx,bx           ;start search at segment zero (really 1)
  605.                 mov     ax,cs           ;compare to current code segment
  606. start1:         inc     bx              ;look at next segment
  607.                 cmp     ax,bx           ;until reaching this code seg
  608.                 mov     es,bx
  609.                 je      start3
  610.                 mov     si,offset go    ;set up to compare strings
  611.                 mov     di,si
  612.                 mov     cx,16           ;16 bytes must match
  613.                 rep     cmpsb           ;compare ds:si to es:di
  614.                 or      cx,cx           ;did the strings match?
  615.                 jnz     start1          ;if no match, try next segment
  616.                                         ;else fall through (already installed)
  617.                                         ; with es -> matching code segment
  618.                 cmp     CmdLineParm,'-' ;unchain
  619.                 jne     startR
  620.                 jmp     Unchain
  621. startR:         and     CmdLineParm,255-32  ;make it uppercase
  622.                 cmp     CmdLineParm,'R' ;restore 26 lines; awaken if dormant
  623.                 jne     startD
  624.                 jmp     RedoStatLn
  625. startD:         cmp     CmdLineParm,'D' ;sleep
  626.                 jne     startA
  627.                 jmp     Sleep
  628. startA:         cmp     CmdLineParm,'A' ;autopark
  629.                 jne     start?
  630.                 jmp     AutoPark
  631. start?:         lea     dx,Use
  632.                 cmp     CmdLineParm,0
  633.                 jne     start2          ;invalid parm
  634.                 lea     dx,DupMsg       ;no parms?,(/) already installed msg
  635. start2:         mov     ah,9
  636.                 int 21h
  637.                 mov     al,1
  638.                 jmp     Exit4c
  639.  
  640. start3:         lea     dx,Use          ;we're not installed
  641.                 mov     ah,9
  642.                 int 21h
  643.                 jmp     notinstalled
  644.  
  645.                 ;---------------------
  646.                 ;es->match segment
  647. AutoPark:       mov     es:ticks,0      ;set TSR data
  648.                 mov     es:Parked,0
  649.                 mov     es:JustPark,0
  650.                 mov     es:DoAuto,1
  651.  
  652.                 lea     dx,AutoMsg
  653.                 mov     ah,9
  654.                 int 21h
  655.                 mov     al,0
  656.                 jmp     Exit4c
  657.  
  658.                 ;---------------------
  659. Sleep:          push    es              ;save TSR's segment
  660.                 mov     ax,351Ch        ;get current timer interrupt (1Ch)
  661.                 int     21h
  662.                 pop     ax
  663.                 mov     dx,es
  664.                 cmp     ax,dx           ;compare matched seg with 1Ch seg
  665.                 jne     Sleep2          ;cannot sleep since seg has changed
  666.                 push    ax
  667.                 pop     es              ;get back es
  668.                 mov     dx,es:word ptr Old_1C
  669.                 mov     ax,es:word ptr Old_1C+2
  670.                 mov     ds,ax
  671.                 mov     ax,251Ch
  672.                 int 21h
  673.                 mov     ax,cs           ;restore ds
  674.                 mov     ds,ax
  675.                 call    Get_Video_Info
  676.                 cmp     VALIDMODE,1
  677.                 mov     ax,0
  678.                 push    ax              ;save errorlevel
  679.                 jne     Sleep1
  680.                 call    Set_Line25      ;only if in a valid mode
  681. Sleep1:         lea     dx,SleepMsg
  682.                 jmp     short Sleep3
  683. Sleep2:         lea     dx,NoSleepMsg
  684.                 mov     ax,1
  685.                 push    ax              ;save errorlevel
  686. Sleep3:         mov     ah,9
  687.                 int 21h
  688.                 pop     ax
  689.                 jmp     Exit4c
  690.                 
  691.                 ;---------------------
  692. RedoStatLn:     push    es              ;save es
  693.                 call    Get_Video_Info
  694.                 pop     es
  695.                 cmp     VALIDMODE,1
  696.                 je      RedoStatLn1
  697.                 lea     dx,NoRestoreMsg
  698.                 mov     ah,9
  699.                 int 21h
  700.                 mov     al,1
  701.                 jmp     Exit4c
  702. RedoStatLn1:    call    Set_Line26
  703.                 lea     dx,Redo26Msg
  704.                 mov     ah,9
  705.                 int 21h
  706.                 push    es              ;save es
  707.                 mov     ax,351Ch        ;get current timer interrupt (1Ch)
  708.                 int     21h             ; since it may have changed
  709.                 mov     cx,es           ;save int 21h's es into cx
  710.                 pop     es              ;get back es
  711.                 mov     dx,es
  712.                 cmp     cx,dx           ;if interrupt 1Ch has changed
  713.                 jne     RedoStatLn2     ; then need to awaken
  714.                 je      RedoStatLn3
  715. RedoStatLn2:    mov     es:word ptr [Old_1C],bx    ;save current offset in TSR
  716.                 mov     es:word ptr [Old_1C+2],cx  ;save current segment
  717.                 mov     dx,offset New_1C
  718.                 push    es
  719.                 pop     ds              ;matching code seg
  720.                 ASSUME  ds:NOTHING
  721.                 mov     ax,251Ch
  722.                 int     21h             ;set interrupt (1Ch) (time to awaken)
  723.                 push    cs
  724.                 pop     ds              ;get back ds
  725.                 ASSUME  ds:DriveST_SEG
  726. RedoStatLn3:    mov     ah,0
  727.                 jmp     Exit4c
  728.  
  729.                 ;---------------------
  730.                 ;es -> matching segment
  731. Unchain:        push    es              ;save TSR's segment
  732.                 mov     ax,351Ch        ;get current timer interrupt (1Ch)
  733.                 int     21h
  734.                 pop     ax
  735.                 mov     dx,es
  736.                 cmp     ax,dx           ;compare matched seg with 1Ch seg
  737.                 jne     Unchain4        ;cannot unchain since seg has changed
  738.                 mov     es,ax           ;get back es
  739.                 mov     dx,es:word ptr Old_1C
  740.                 mov     ax,es:word ptr Old_1C+2
  741.                 mov     ds,ax
  742.                 mov     ax,251Ch        ;set timer interrupt to interrupt valid
  743.                 int 21h                 ; when installed
  744.                 mov     ax,cs           ;restore ds
  745.                 mov     ds,ax
  746.  
  747.                 not     es:byte ptr go  ;precludes matching on next install
  748.  
  749.                 mov     cx,es           ;save es -> PSP/COM BLOCK (not in EXE's)
  750.                 mov     bx,es:[002Ch]   ;segment address of environment block
  751.                 mov     es,bx
  752.                 mov     ah,49h
  753.                 int 21h                 ;release the environment block
  754.                 jc      Unchain1        ;an error
  755.  
  756.                 mov     es,cx
  757.                 mov     ah,49h          ;release the TSR block
  758.                 int 21h
  759.                 jnc     Unchain2
  760.  
  761. Unchain1:       lea     dx,DeAllocMsg   ;memory dealloc error
  762.                 mov     ah,9
  763.                 int     21h
  764.                 mov     al,1
  765.                 jmp     short Exit4c
  766.  
  767. Unchain2:       call    Get_Video_Info
  768.                 cmp     VALIDMODE,1
  769.                 jne     Unchain3
  770.                 call    Set_Line25      ;only if in a valid mode
  771.  
  772. Unchain3:       lea     dx,UniMsg
  773.                 mov     ah,9
  774.                 int 21h
  775.                 mov     al,00h
  776.  
  777.                 ;---------------------
  778. Exit4c:         mov     ah,4Ch
  779.                 int 21h
  780.  
  781.                 ;---------------------
  782. Unchain4:       lea     dx,NoUnchain
  783.                 mov     ah,9
  784.                 int 21h
  785.                 mov     al,1
  786.                 jmp     short Exit4c
  787.  
  788.                 ;---------------------
  789. notinstalled:   cmp     CmdLineParm,0   ;not yet installed, should be no parms
  790.                 je      notinstalled1
  791.                 lea     dx,NotInstalledMsg
  792.                 mov     ah,9
  793.                 int 21h
  794.                 mov     al,1
  795.                 jmp     short Exit4c
  796.  
  797.                 ;---------------------
  798. notinstalled1:  call    Get_Video_Info
  799.                 cmp     VALIDMODE,1     ;are we in a valid mode?
  800.                 je      notinstalled2
  801.                 lea     dx,NoInstallMsg
  802.                 mov     ah,9
  803.                 int 21h
  804.                 mov     al,1
  805.                 jmp     short Exit4c
  806.  
  807.                 ;---------------------
  808. notinstalled2:  mov     ax,351Ch        ;get timer interrupt (1Ch)
  809.                 int     21h
  810.                 mov     word ptr [Old_1C],bx    ;save offset
  811.                 mov     word ptr [Old_1C+2],es  ;save segment
  812.                 mov     dx,offset New_1C
  813.                 mov     ax,251Ch
  814.                 int     21h             ;set new interrupt (1Ch)
  815.  
  816.                 call    Set_Line26
  817.  
  818.                 call    EntryAt
  819.                 lea     dx,EntryAtMsg   ;1Ch entry address
  820.                 mov     ah,9
  821.                 int 21h
  822.  
  823.                 mov     dx,offset start
  824.                 mov     cl,4
  825.                 shr     dx,cl
  826.                 inc     dl
  827.                 inc     dl
  828.                 mov     ax,3100h
  829.                 int     21h     ;Terminate - stay resident (keep up to start)
  830.  
  831. subttl Installation called routines
  832.  
  833.                 ;---------------------
  834. GetParm:        mov     si,81h
  835.                 mov     CmdLineParm,0
  836. GetParm1:       mov     bl,[si]
  837.                 cmp     bl,0dh
  838.                 je      GetParm_Exit
  839.                 inc     si
  840.                 cmp     bl,'/'
  841.                 jne     GetParm1
  842.                 mov     bl,[si]
  843.                 mov     CmdLineParm,bl
  844. GetParm_Exit:   ret
  845.  
  846. ;
  847. ; byte in al to two-byte ASCII hex in ax (A5 to 'A5')
  848. ;
  849.  
  850. ConvByte2ASCII  PROC NEAR
  851.                 ASSUME  ds:DriveST_SEG
  852.  
  853.                 push    cx
  854.                 mov     cl,4            ;mult x 16
  855.                 xor     ah,ah           ;just the low-order byte
  856.                 push    ax              ;save data passed in AX
  857.                 and     al,0F0h         ;hi-order nybble
  858.                 shr     al,cl           ;div hi-nybble by 16
  859. ConvB:          cmp     al,9            ;hex letter?
  860.                 jna     ConvBdec
  861.                 add     al,55           ;10+55=65(A)
  862.                 jmp     short ConvB1
  863. ConvBdec:       add     al,'0'          ;adjust ASCII to decimal 9+30h(0)=39h(9)
  864. ConvB1:         cmp     cl,0            ;done both ASCII bytes?
  865.                 je      ConvB2          ;*** exit 2x loop here
  866.                 xchg    al,ch           ;save it
  867.                 pop     ax              ;get it again
  868.                 and     al,0Fh          ;low-order nybble
  869.                 mov     cl,0            ;make it last time around
  870.                 jmp     short ConvB     ;do low-order nybble
  871. ConvB2:         xchg    ch,ah           ;get hi-order
  872.                 xchg    al,ah           ;put in correct order
  873.                 clc                     ;and we're done
  874.                 pop     cx
  875.                 ret
  876.  
  877. ConvByte2ASCII  endp
  878.  
  879. ;
  880. ; get 1Ch entry address
  881. ;
  882.  
  883. EntryAt         PROC NEAR
  884.                 ASSUME  ds:DriveST_SEG
  885.  
  886.                 mov     bx,offset EntryAtMsg+7
  887.                 mov     ax,cs
  888.                 xchg    ah,al
  889.                 call    ConvByte2ASCII  ;seg high byte
  890.                 mov     word ptr [bx],ax
  891.                 mov     ax,cs
  892.                 call    ConvByte2ASCII  ;seg low byte
  893.                 mov     word ptr [bx+2],ax
  894.                 mov     ax,offset New_1C
  895.                 xchg    ah,al
  896.                 call    ConvByte2ASCII  ;off high byte
  897.                 mov     word ptr [bx+5],ax
  898.                 mov     ax,offset New_1C
  899.                 call    ConvByte2ASCII  ;off low byte
  900.                 mov     word ptr [bx+7],ax
  901.                 ret
  902.  
  903. EntryAt         ENDP
  904.  
  905. subttl Installation messages
  906.  
  907. DeAllocMsg      db '*** Error in releasing memory - suggest a REBOOT ASAP!'
  908.                 db 13,10,7,'$'
  909. NoSleepMsg      db '*** Cannot become dormant - interrupt 1Ch has changed.'
  910.                 db 13,10,7,'$'
  911. NoInstallMsg    db '*** Cannot install - must be in BIOS video modes 2, 3, or 7.'
  912.                 db 13,10,7,'$'
  913. NoRestoreMsg    db '*** Cannot restore - must be in BIOS video modes 2, 3, or 7.'
  914.                 db 13,10,7,'$'
  915. NoUnchain       db '*** Cannot remove from memory - interrupt 1Ch has changed.'
  916.                 db 13,10,7,'$'
  917. NotInstalledMsg db '*** Parameter ignored - DST is NOT installed.'
  918.                 db 13,10,7,'$'
  919. DupMsg          db '*** Already installed - use DST /r to restore.'
  920.                 db 13,10,7,'$'
  921. Copyright       db 'DST 1.0 - Public Domain material brought to you by Cornel Huth. '
  922.                 db 13,10,'$'
  923. Use             db 13,10
  924.                 db 'Use:  DST     * install TSR ',13,10
  925.                 db '      DST /-  * remove from memory ',13,10
  926.                 db '      DST /d  * make dormant ',13,10
  927.                 db '      DST /r  * restore status line; awaken if dormant ',13,10
  928.                 db '      DST /a  * activate autopark of hard disk C: ',13,10
  929.                 db 13,10,'$'
  930. EntryAtMsg      db '[0x1C] 0000:0000 '
  931.                 db 13,10,'$'
  932. UniMsg          db 'Released from memory.  Use DST to install again.'
  933.                 db 13,10,'$'
  934. SleepMsg        db 'Dormant.  Use DST /r to restore.'
  935.                 db 13,10,'$'
  936. Redo26Msg       db 'Restored.'
  937.                 db 13,10,'$'
  938. AutoMsg         db 'Autopark of hard disk C: activated.'
  939.                 db 13,10,'$'
  940.  
  941. DriveST_SEG     ENDS
  942.                 END go
  943.  
  944.